#include<iostream>
#include<memory>    //智能指针
#include<string>
#include"UdpServer.hpp"   //网络通信的功能(作为底层)
#include"Route.hpp"    //路由头文件
#include"ThreadPool.hpp"

using namespace ThreadPoolModule;

//这个就达成了对于一个字符串做什么处理（仅做测试）
std::string defaulthandler(const std::string &message)   //收到一个message
{
    std::string hello = "hello, ";
    hello += message;
    return hello;
}


using task_t = std::function<void()>;


//未来启动  ./udpserver ip port （用命令行参数）
int main(int argc,char *argv[])
{
    if(argc != 2)    //如果不为2，也就报错，给用户说明要怎么使用       因为不需要ip
    {
        std::cerr << "Usage: " << argv[0] << " port" << std::endl;
        return 1;
    }

    // std::string ip = argv[1];      ip不要了
    uint16_t port = std::stoi(argv[1]);     //把argvp[1] 字符串转化为整数    ip不要 只有1
    Enable_Console_Log_Strategy();        //开启日志， 显示日志到显示器上

//路由是由Route模块完成
    //1. 路由服务（回头代码推送到路由模块，而非之前的翻译模块）
    Route r;     //构建Route对象 r

    //2.线程池
    auto tp = ThreadPool<task_t>::GetInstance();   //线程池里面存放任务task_t对象，GetInstance 获得线程池所对应的对象
    
    //3. 网络服务器对象，提供通信功能(peer表示谁发的消息)
    //当服务器收到了消息，不应r进行发送，而是应该把任务推送到线程池，由线程池的线程执行发送，UdpServer收到消息
    //只需构建一个任务，把任务扔线程池里

    //服务器要向线程池中入队列，参数port   要执行对应的方法：[](){}
    //线程池要路由的方法打包变成一个方法，作为一个任务push到线程池中，要把对应的对象传进来
    //要把几个东西合一起     传参数int sockfd,const std::string &message,InetAddr &peer
    std::unique_ptr<UdpServer> usvr = std::make_unique<UdpServer>(port,[&r,&tp](int sockfd,const std::string 
    &message,InetAddr &peer){
        //有了对应的任务，任务用的就是r里的MessageRoute      MessageRoute里的参数是 sockfd,message,peer
        task_t t = std::bind(&Route::MessageRoute,&r,sockfd,message,peer);   //参数绑定    前两个都是指针（&）
        //任务入队
        tp->Enqueue(t);
    }); 

    // std::unique_ptr<UdpServer> usvr = std::make_unique<UdpServer>(port,[&r](int sockfd,const std::string &message,
    // InetAddr &peer){
    //     r.MessageRoute(sockfd,message,peer);   //要带上文件描述符  sockfd
    // }); 

    usvr->Init();      //构造函数的时候，把回调函数传进去
    usvr->Start();


    return 0;
}